package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repository.IStrategyRepository;
import cn.wolfcode.luowowo.search.service.IStrategyTemplateSearchService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyTemplateSearchServiceImpl implements IStrategyTemplateSearchService {

    @Autowired
    private IStrategyRepository repository;

    @Autowired
    private ElasticsearchTemplate template;


    @Override
    public void saveOrUpdate(StrategyTemplate template) {
        repository.save(template);
    }


    private List<StatisVO> statisGroup(String idField, String nameField, String groupName, BoolQueryBuilder query){
        List<StatisVO> list = new ArrayList<>();
        //查询维度设置
        //分组维度集合对象
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();

        //第一个分组维度对象:themeId
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        idSource.missingBucket(true);//忽略不满足条件的bucket
        sources.add(idSource);
        //第二个分组维度封装对象:themeName
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);
        nameSource.missingBucket(true);//忽略不满足条件的bucket
        sources.add(nameSource);

        //参数一:分组名称
        //参数二:分组维度集合
        CompositeAggregationBuilder abuilder = new CompositeAggregationBuilder(groupName, sources);

        /////////////////////////////////////查询搜索操作
        //查询语句封装对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withIndices(StrategyTemplate.INDEX_NAME);//索引
        builder.withTypes(StrategyTemplate.TYPE_NAME);//类型
        builder.addAggregation(abuilder);//添加聚合查询构建模块
        builder.withPageable(PageRequest.of(0,1));//jpa规范中不允许pagesize为0

        if(query != null){
            builder.withQuery(query);
        }
        //////////////////////////查询搜索操作//////////////////////////
        //查询结果:要聚合的数据
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        //从查询结果中获取需要的数据:聚合数据
        InternalComposite aggregation = page.getAggregations().get(groupName);

        StatisVO vo = null;
        for (CompositeAggregation.Bucket bucket : aggregation.getBuckets()) {
            vo = new StatisVO();
            if(bucket.getKey().get("id") == null){
                continue;
            }
            vo.setName(bucket.getKey().get("name").toString());
            vo.setCount(bucket.getDocCount());
            vo.setId(Long.parseLong(bucket.getKey().get("id").toString()));
            list.add(vo);
        }

        //优化点1:排序,按照count的倒叙排
        list.sort(new Comparator<StatisVO>() {
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                return (int) (o2.getCount() - o1.getCount());
            }
        });


        return list;

    }


    @Override
    public List<StatisVO> queryCondition(int condition) {
        if(condition == StrategySearchQuery.CONDITION_CHINA){
            return this.statisGroup("provinceId","provinceName","provinceGroup",null);//国内
        }else if(condition == StrategySearchQuery.CONDITION_THEME){
            return this.statisGroup("themeId","themeName","themeGroup",null);//主题
        }else if(condition == StrategySearchQuery.CONDITION_ABROAD){
            //优化点二:海外不包含国内
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.mustNot(QueryBuilders.termQuery("countryId",1));
            return this.statisGroup("countryId","countryName","countryGroup",query);//海外

        }

        return null;
    }

    @Override
    public Page query(StrategySearchQuery qo) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        //国内
        if(qo.getType() == StrategySearchQuery.CONDITION_CHINA){
            query.must(QueryBuilders.termQuery("provinceId",qo.getTypeValue()));

        }else if(qo.getType() == StrategySearchQuery.CONDITION_ABROAD){
            //海外
            query.must(QueryBuilders.termQuery("countryId",qo.getTypeValue()));
        }else if(qo.getType() == StrategySearchQuery.CONDITION_THEME){
            //主题
            query.must(QueryBuilders.termQuery("themeId",qo.getTypeValue()));
        }
        return repository.search(query,qo.getPageable());
    }

    @Override
    public List<Map<String, Object>> queryThemeCommend() {
        List<Map<String,Object>> list = new ArrayList<>();
        //1.查询数量在前10的推荐
        List<StatisVO> themesVo = this.statisGroup("themeId", "themeName", "themeGroup", null);//查询出来的是所有主题类型
        if(themesVo.size() > 10){
            themesVo = themesVo.subList(0, 10);
        }
        Map<String,Object> map = null;
        for (StatisVO vo : themesVo) {
            map = new HashMap<>();
            map.put("theme",vo);
            map.put("dests",this.getDestByThemeId(vo.getId()));//当前主题下的所有攻略的目的地集合
            list.add(map);
        }

        return list;
    }

    @Override
    public List<StrategyTemplate> findByDestName(String keyword) {
        return repository.findByDestName(keyword);
    }

    //通过主题id查询es中luowowo_strategy找文档中的id跟名字
    private List<StatisVO> getDestByThemeId(Long id){
        Iterable<StrategyTemplate> iterable = repository.search(QueryBuilders.termQuery("themeId", id));

        List<StatisVO> list = new ArrayList<>();

        /*Iterator<StrategyTemplate> iterator = iterable.iterator(); //迭代器
        while (iterator.hasNext()){
            list.add(iterator.next());
        }*/
        List<String> names = new ArrayList<>();
        iterable.forEach(st-> {
            if(!names.contains(st.getDestName())){
                StatisVO vo = new StatisVO();
                vo.setId(st.getDestId());
                vo.setName(st.getDestName());
                list.add(vo);
                names.add(st.getDestName());
            }

        });

        return list;
    }
}
